//---------------------------------------------------------------------------------
// Copyright (c) 2011, Microsoft Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//---------------------------------------------------------------------------------

namespace Microsoft.Samples.ServiceBus.SilverlightChat.Models.Commands
{
    using System;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Input;
    using Microsoft.Samples.ServiceBus;
    using Microsoft.Samples.ServiceBus.Messaging;
    using Microsoft.Samples.ServiceBus.SilverlightChat.Models.ViewModels;

    /// <summary>
    /// Encapsulates a command to add a new topic (and optionally, a subscription to that topic) to
    /// the service namespace
    /// </summary>
    public class AddTopicCommand : ICommand
    {
        private readonly ChatWindowViewModel viewModel;

        public AddTopicCommand(ChatWindowViewModel viewModel)
        {
            if (viewModel == null)
            {
                throw new ArgumentNullException("viewModel");
            }

            this.viewModel = viewModel;
        }

        public event EventHandler CanExecuteChanged;

        public ChatWindowViewModel ViewModel
        {
            get { return this.viewModel; }
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            // Begin executing by showing the 'Add Topic' dialog which asks a user to specify a
            // topic name and check box to immediately subscribe to the new topic.
            var dialog = ((MainPage)App.Current.RootVisual).addTopicDialog;
            dialog.Show(this.DialogClosed);
        }

        protected void OnCanExecuteChanged(object sender, EventArgs e)
        {
            if (this.CanExecuteChanged != null)
            {
                this.CanExecuteChanged(sender, e);
            }
        }

        private void DialogClosed(AddTopicDialog dialog, bool cancelled)
        {
            // When the dialog closes, read the name of the topic and boolean value indicating if
            // a subscription to the new topic should be created
            if (!cancelled)
            {
                var newTopicName = Uri.EscapeDataString(dialog.NewTopicName);
                var shouldSubscribe = dialog.Subscribe;

                // Asynchronously begin creating a new topic with the Silverlight API
                TopicClient.BeginCreateTopic(newTopicName, App.Context.TokenProvider, this.TopicCreated, shouldSubscribe);
            }
        }

        private void TopicCreated(IAsyncResult result)
        {
            // When the request to create the topic has completed, end the Async call
            var shouldSubscribe = (bool)result.AsyncState;
            TopicClient topicClient = null;
            HttpWebException exception = null;

            try
            {
                topicClient = TopicClient.EndCreateTopic(result);
            }
            catch (HttpWebException e)
            {
                exception = e;
            }

            // Update the UI with the result of the 'Add Topic' command
            this.ViewModel.Dispatcher.BeginInvoke(() =>
            {
                if (topicClient != null)
                {
                    // Add the new topic to the topics list
                    this.ViewModel.Topics.AddTopics(topicClient);

                    if (shouldSubscribe)
                    {
                        // The user opted to immediately subsribe to this topic - find the newly 
                        // created ViewModel for this topic and invoke the SubscribeToTopic command 
                        // on it.
                        var newTopicViewModel = this.ViewModel.Topics.First(vm => vm.TopicClient == topicClient);
                        newTopicViewModel.SubscribeCommand.Execute(newTopicViewModel);
                    }
                }
                else
                {
                    if (exception != null)
                    {
                        // A HTTP 409 error indicates that the Topic already exists, so cannot be 
                        // created
                        if (exception.StatusCode == HttpStatusCode.Conflict)
                        {
                            MessageBox.Show("Cannot create the new topic, because a topic with that name already exists.");
                        }
                    }
                }
            });
        }
    }
}
